package br.edu.ufcg.lsd.wbis.control.util;

import java.io.File;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

/**
 * This class provides utilities for using the Hibernate persistence framework
 * 
 * @author Paulo Ricardo
 * @author Renato Miceli
 */
public class HibernateUtil {

	private final SessionFactory sessionFactory;

	private static HibernateUtil instance;

	private HibernateUtil() {
		this(getDefaultConfigFilePath());
	}

	private HibernateUtil(String confFileDir) {
		try {
			// Create the SessionFactory from the config file
			File wbisConf = new File(confFileDir);
			this.sessionFactory = new AnnotationConfiguration().configure(wbisConf).buildSessionFactory();
		} catch (Throwable ex) {
			// Make sure you log the exception, as it might be swallowed
			System.err.println("Initial SessionFactory creation failed." + ex);
			throw new ExceptionInInitializerError(ex);
		}
	}

	/**
	 * Gets the current instance of this singleton
	 * 
	 * @return the instance
	 */
	public static HibernateUtil getInstance() {
		if (instance == null) {
			instance = new HibernateUtil();
		}
		return instance;
	}

	/**
	 * Used for test purposes
	 * 
	 * @param hibernateXmlConfDir
	 *            The configuration file path
	 */
	public static HibernateUtil getInstance(String hibernateXmlConfDir) {
		if (instance != null) {
			instance.closeSessionFactory();
		}
		instance = new HibernateUtil(hibernateXmlConfDir);
		return instance;
	}

	/**
	 * Closes the session factory (and consequently the connection to the DB)
	 */
	private void closeSessionFactory() {
		this.getSessionFactory().close();
	}

	/**
	 * Gets the session factory for the current configuration
	 * 
	 * @return session factory
	 */
	public SessionFactory getSessionFactory() {
		return this.sessionFactory;
	}

	/**
	 * Retrieves the path to the file used for configuring Hibernate.
	 * 
	 * @return the file path for configuring Hibernate.
	 */
	public static String getDefaultConfigFilePath() {
		return HibernateUtil.class.getResource("/hibernate.cfg.xml").getPath();
	}

	/**
	 * Retrieves the path to the file used for configuring Hibernate in testing
	 * mode.
	 * 
	 * @return the path to the file used for configuring Hibernate in testing
	 *         mode.
	 */
	public static String getTestingConfigFilePath() {
		return HibernateUtil.class.getResource("/test.cfg.xml").getPath();
	}

}
